#include "conn_reader.h"

#include <unistd.h>
#include <arpa/inet.h>

#include <string>

#include "log.h"
#include "packet_base.h"

ConnReader::ConnReader(){
    Reset();
}

ConnReader::~ConnReader(){
}

void ConnReader::Reset(){
    memset(buff_, 0, common::PROTO_BUFFER_LEN);
    index_ = 0;
    origin_body_len_ = 0;
    origin_cmd_ = 0;
    body_len_ = 0;
    cmd_ = 0;
}

ConnReader::EStatus ConnReader::ReadHeader(){
    int len = ::read(fd_, buff_ + index_, common::PROTO_HEADER_LEN - index_);
    if(len == -1){
        if (errno == EAGAIN || errno == EWOULDBLOCK) {
            return EStatus::kEAGAIN; // 数据已读完
        }

        LOG_ERR("recv error, fd:{}", fd_);
        ::close(fd_);
        return EStatus::kERROR;
    }else if(len == 0){
        LOG_DEBUG("conn close, fd:{}", fd_);
        ::close(fd_);
        return EStatus::kCLOSE;
    }
    
    if(len + index_ == common::PROTO_HEADER_LEN){
        memcpy(&origin_body_len_, buff_, common::PROTO_HEAD_CMD_LEN - index_);
        body_len_ = ntohs(origin_body_len_);
        LOG_DEBUG("body_len:{}", body_len_);

        memcpy(&origin_cmd_, buff_ + common::PROTO_HEAD_CMD_LEN, common::PROTO_HEAD_CMD_LEN);
        cmd_ = ntohs(origin_cmd_);
        LOG_DEBUG("cmd_:{}", cmd_);

        memset(buff_, 0, common::PROTO_BUFFER_LEN);
        index_ = 0;
        return EStatus::kHEADER_FINISHED;

    }else if(len > 0){
        // 等待更多数据
        index_ += len;
        return EStatus::kEAGAIN;
    }else{
        LOG_ERR("recv error, fd:{}, len:{}", fd_, len);
        ::close(fd_);
        return EStatus::kERROR;
    }
}

ConnReader::EStatus ConnReader::ReadBody(){
    int len = ::read(fd_, buff_ + index_, body_len_ - index_);
    if(len == -1){
        if (errno == EAGAIN || errno == EWOULDBLOCK) {
            return EStatus::kEAGAIN; // 数据已读完
        }

        LOG_ERR("recv error, fd:{}", fd_);
        ::close(fd_);
        return EStatus::kERROR;
    }else if(len == 0){
        LOG_DEBUG("conn close, fd:{}", fd_);
        ::close(fd_);
        return EStatus::kCLOSE;
    }
    
    if(len + index_ == body_len_){
        index_ = 0;
        return EStatus::kBODY_FINISHED;

    }else if(len > 0){
        // 等待更多数据
        index_ += len;
        return EStatus::kEAGAIN;
    }else{
        LOG_ERR("recv error, fd:{}, len:{}", fd_, len);
        ::close(fd_);
        return EStatus::kERROR;
    }
}

int ConnReader::Recv(){
    EStatus status;
    while(true){
        if(body_len_ == 0){
            status = ReadHeader();
        }else{
            status = ReadBody();
        }

        if(status == EStatus::kBODY_FINISHED){
            HandleData();
        }else if(status == EStatus::kEAGAIN){
            return 0;
        }else if(status == EStatus::kCLOSE || status == EStatus::kERROR){
            return -1;
        }
    }

    return 1;
}

void ConnReader::HandleData(){

    PacketBase packet;
    packet.Reset();
    packet.CopyHeader(origin_body_len_, origin_cmd_);
    packet.CopyBody(buff_, body_len_);
    LOG_DEBUG("data body:{}, body_len:{}, cmd:{}", packet.ReadInt16(), packet.GetBodySize(), packet.GetCmd());
    packet.ResetPos();

    cb_(fd_, packet);

    Reset();
}
